package com.it.schoolbookshop_back.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.schoolbookshop_back.entities.po.Notification;
import com.it.schoolbookshop_back.entities.po.UserSettings;
import com.it.schoolbookshop_back.enums.NotificationType;
import com.it.schoolbookshop_back.mapper.NotificationMapper;
import com.it.schoolbookshop_back.mapper.UserSettingsMapper;
import com.it.schoolbookshop_back.service.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通知服务实现类
 */
@Slf4j
@Service
public class NotificationServiceImpl implements NotificationService {
    
    @Autowired
    private NotificationMapper notificationMapper;
    
    @Autowired
    private UserSettingsMapper userSettingsMapper;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    // 存储所有活跃的WebSocket会话，从ChatWebSocketHandler中获取
    private static final Map<Integer, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    
    @Override
    public boolean createNotification(Integer userId, NotificationType type, String content, Integer relatedId) {
        try {
            // 创建通知记录，无论用户设置如何，都会保存到数据库
            Notification notification = new Notification();
            notification.setUserId(userId);
            notification.setType(type.getType());
            notification.setContent(content);
            notification.setRelatedId(relatedId);
            notification.setIsRead(false);
            
            // 保存通知到数据库
            int result = notificationMapper.insertNotification(notification);
            
            // 获取用户设置，决定是否发送WebSocket消息
            UserSettings userSettings = userSettingsMapper.getByUserId(userId);
            if (userSettings != null) {
                // 根据通知类型和用户设置决定是否发送WebSocket消息
                boolean shouldSendWebSocket = false;
                
                switch (type) {
                    case MESSAGE:
                        shouldSendWebSocket = userSettings.getNotificationMessages();
                        break;
                    case FAVORITE:
                        shouldSendWebSocket = userSettings.getNotificationFavorites();
                        break;
                    case TRANSACTION:
                        shouldSendWebSocket = userSettings.getNotificationTransactions();
                        break;
                }
                
                // 如果用户设置允许，则发送WebSocket消息
                if (shouldSendWebSocket) {
                    sendWebSocketNotification(userId, type.getType(), content, notification.getId());
                }
            }
            
            return result > 0;
        } catch (Exception e) {
            log.error("创建通知失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public List<Notification> getUserNotifications(Integer userId) {
        return notificationMapper.getNotificationsByUserId(userId);
    }
    
    @Override
    public List<Notification> getUserNotificationsByType(Integer userId, NotificationType type) {
        return notificationMapper.getNotificationsByUserIdAndType(userId, type.getType());
    }
    
    @Override
    public boolean markAsRead(Integer notificationId) {
        return notificationMapper.markAsRead(notificationId) > 0;
    }
    
    @Override
    public boolean markAllAsRead(Integer userId) {
        return notificationMapper.markAllAsRead(userId) > 0;
    }
    
    @Override
    public int getUnreadCount(Integer userId) {
        return notificationMapper.getUnreadCount(userId);
    }
    
    @Override
    public int getUnreadCountByType(Integer userId, NotificationType type) {
        return notificationMapper.getUnreadCountByType(userId, type.getType());
    }
    
    @Override
    public boolean deleteNotification(Integer notificationId) {
        return notificationMapper.deleteNotification(notificationId) > 0;
    }
    
    /**
     * 发送WebSocket通知给用户
     *
     * @param userId 用户ID
     * @param content 通知内容
     * @return 是否发送成功
     */
    @Override
    public boolean sendWebSocketNotification(Integer userId, String content) {
        return sendWebSocketNotification(userId, "unknown", content, null);
    }
    
    /**
     * 发送WebSocket通知给用户（增强版，含类型）
     *
     * @param userId 用户ID
     * @param type 通知类型
     * @param content 通知内容
     * @param notificationId 通知ID
     * @return 是否发送成功
     */
    public boolean sendWebSocketNotification(Integer userId, String type, String content, Integer notificationId) {
        // 获取用户的WebSocket会话
        WebSocketSession session = userSessions.get(userId);
        if (session != null && session.isOpen()) {
            try {
                // 构建消息内容 - 适配前端格式
                Map<String, Object> message = new HashMap<>();
                message.put("type", "NOTIFICATION");
                message.put("notificationType", type);
                message.put("content", content);
                message.put("timestamp", System.currentTimeMillis());
                
                if (notificationId != null) {
                    message.put("id", notificationId);
                }
                
                // 发送消息
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(message)));
                log.info("已成功发送WebSocket通知[{}]给用户: {}", type, userId);
                return true;
            } catch (IOException e) {
                log.error("发送WebSocket消息失败: {}", e.getMessage(), e);
            }
        } else {
            log.info("用户 {} 不在线或WebSocket会话未建立", userId);
        }
        return false;
    }
    
    /**
     * 更新用户会话集合，供WebSocket处理器调用
     * 
     * @param userSessionsMap 用户会话集合
     */
    public void setUserSessions(Map<Integer, WebSocketSession> userSessionsMap) {
        userSessions.clear();
        userSessions.putAll(userSessionsMap);
        log.info("通知服务用户会话已更新，当前会话数: {}", userSessions.size());
    }
} 